/*
 * CEntity.cpp
 *
 *  Created on: 27/08/2008
 *      Author: samuel.grigolato
 */

#include "CEntity.h"
#include <typeinfo>
#include <string>

std::vector<CEntity*>* CEntity::EntityList = new std::vector<CEntity*>();

CEntity::CEntity() {
	SurfEntity = NULL;

	X = 0;
	Y = 0;

	TileX = 0;
	TileY = 0;

	Width = 0;
	Height = 0;

	AnimState = 0;

	Trash = false;

	Solido = false;

	PorcentagemFisicaWidth = 0;
	PorcentagemFisicaHeight = 0;
}

bool CEntity::ConfiguraTileVazio(CEntity *Entidade) {
	int LarguraMapa = CParametros::GetLarguraMapa();
	int AlturaMapa = CParametros::GetAlturaMapa();
	bool Achou = false;

	srand(SDL_GetTicks());
	while (Achou == false) {
		double xSeed = ((double) rand() / ((double) (RAND_MAX) + (double) (1)));
		double ySeed = ((double) rand() / ((double) (RAND_MAX) + (double) (1)));
		int X = (int) (xSeed * LarguraMapa);
		int Y = (int) (ySeed * AlturaMapa);

		bool Existe = false;

		for (Uint32 i = 0; i < CEntity::EntityList->size(); i++) {
			if ((*CEntity::EntityList)[i] == NULL)
				continue;
			if ((*CEntity::EntityList)[i] == Entidade)
				continue;
			if ((*CEntity::EntityList)[i]->TileX == X
					&& (*CEntity::EntityList)[i]->TileY == Y) {
				Existe = true;
			}
		}

		if (Existe == false) {
			Achou = true;
			Entidade->TileX = X;
			Entidade->TileY = Y;
		}
	}

	return true;
}

CEntity::~CEntity() {
	//
}

bool CEntity::Init(int Xtile, int Ytile) {
	this->TileX = Xtile;
	this->TileY = Ytile;
	return true;
}

bool CEntity::OnLoad(const char* File, int Width, int Height, int MaxFrames) {
	std::string StrFile = File;
	if ((SurfEntity = CSurface::OnLoad(StrFile)) == NULL) {
		return false;
	}

	CSurface::Transparent(SurfEntity, 255, 0, 255);

	this->Width = Width;
	this->Height = Height;

	ControleAnimacao.MaxFrames = MaxFrames;

	return true;
}

void CEntity::OnLoop() {
	ControleAnimacao.OnAnimate();
}

void CEntity::OnRender(SDL_Surface* SurfDisplay) {
	if (SurfEntity == NULL || SurfDisplay == NULL)
		return;

	CSurface::OnDraw(SurfDisplay, SurfEntity, X, Y, AnimState * Width,
			ControleAnimacao.GetCurrentFrame() * Height, Width, Height);
}

void CEntity::OnCleanup() {
	//
}

void CEntity::ProcessaColisoes(TipoColisao TpColisao) {
	for (Uint32 i = 0; i < CEntity::EntityList->size(); i++) {
		if ((*CEntity::EntityList)[i] == NULL)
			continue;
		if ((*CEntity::EntityList)[i] == this)
			continue;
		if ((*CEntity::EntityList)[i]->TileX == TileX
				&& (*CEntity::EntityList)[i]->TileY == TileY) {
			(*CEntity::EntityList)[i]->ProcessaColisao(this, TpColisao);
		}
	}
}

std::vector<CEntity*> CEntity::RecuperaColisoes() {
	std::vector<CEntity*> colisoes;
	for (Uint32 i = 0; i < CEntity::EntityList->size(); i++) {
		if ((*CEntity::EntityList)[i] == NULL)
			continue;
		if ((*CEntity::EntityList)[i] == this)
			continue;
		if ((*CEntity::EntityList)[i]->Solido == false)
			continue;
		int X = (*CEntity::EntityList)[i]->TileX;
		int Y = (*CEntity::EntityList)[i]->TileY;
		if (Y == this->TileY && X == this->TileX) {
			colisoes.push_back((*CEntity::EntityList)[i]);
		}
	}
	return colisoes;
}

CResultadoColisao CEntity::VerificaColisoes(CRetangulo RetEnt, CEntity *Entidade) {
	std::vector<CEntity*> colisoes;
	CResultadoColisao Resultado;

	CRetangulo RetAtual = Entidade->GetRetangulo();
	for (Uint32 i = 0; i < CEntity::EntityList->size(); i++) {
		if ((*CEntity::EntityList)[i] == NULL)
			continue;
		if ((*CEntity::EntityList)[i] == Entidade)
			continue;
		if ((*CEntity::EntityList)[i]->Solido == false)
			continue;
		if ((*CEntity::EntityList)[i]->TileX == Entidade->TileX &&
				(*CEntity::EntityList)[i]->TileY == Entidade->TileY) {
			continue;
		}

		CResultadoColisao ResultadoTemp;
		CRetangulo RetObs = (*CEntity::EntityList)[i]->GetRetangulo();

		if (RetEnt.D < RetObs.B && RetEnt.D > RetObs.D && RetAtual.C > RetObs.A && RetAtual.A < RetObs.C) {
			ResultadoTemp.ColidiuB = true;
		}

		if (RetEnt.B > RetObs.D && RetEnt.B < RetObs.B && RetAtual.C > RetObs.A && RetAtual.A < RetObs.C) {
			ResultadoTemp.ColidiuD = true;
		}

		if (RetEnt.A < RetObs.C && RetEnt.A > RetObs.A && RetAtual.B > RetObs.D && RetAtual.D < RetObs.B) {
			ResultadoTemp.ColidiuC = true;
		}

		if (RetEnt.C > RetObs.A && RetEnt.C < RetObs.C && RetAtual.B > RetObs.D && RetAtual.D < RetObs.B) {
			ResultadoTemp.ColidiuA = true;
		}

		bool ColidiuPrevisaoA = RetEnt.C > RetObs.A && RetEnt.C < RetObs.C && RetEnt.B > RetObs.D && RetEnt.D < RetObs.B;
		bool ColidiuPrevisaoB = RetEnt.D < RetObs.B && RetEnt.D > RetObs.D && RetEnt.C > RetObs.A && RetEnt.A < RetObs.C;
		bool ColidiuPrevisaoC = RetEnt.A < RetObs.C && RetEnt.A > RetObs.A && RetEnt.B > RetObs.D && RetEnt.D < RetObs.B;
		bool ColidiuPrevisaoD = RetEnt.B > RetObs.D && RetEnt.B < RetObs.B && RetEnt.C > RetObs.A && RetEnt.A < RetObs.C;

		if (ColidiuPrevisaoA && ColidiuPrevisaoB) {
			if (RetObs.B > RetAtual.D) {
				ResultadoTemp.ColidiuA = true;
			} else {
				ResultadoTemp.ColidiuB = true;
			}
		}

		if (ColidiuPrevisaoB && ColidiuPrevisaoC) {
			if (RetObs.B > RetAtual.D) {
				ResultadoTemp.ColidiuC = true;
			} else {
				ResultadoTemp.ColidiuB = true;
			}
		}

		if (ColidiuPrevisaoC && ColidiuPrevisaoD) {
			if (RetObs.D < RetAtual.B) {
				ResultadoTemp.ColidiuC = true;
			} else {
				ResultadoTemp.ColidiuD = true;
			}
		}

		if (ColidiuPrevisaoD && ColidiuPrevisaoA) {
			if (RetObs.D < RetAtual.B) {
				ResultadoTemp.ColidiuA = true;
			} else {
				ResultadoTemp.ColidiuD = true;
			}
		}

		if (ResultadoTemp.ColidiuA || ResultadoTemp.ColidiuC) {
			Resultado.TileX = (*CEntity::EntityList)[i]->TileX;
		}

		if (ResultadoTemp.ColidiuB || ResultadoTemp.ColidiuD) {
			Resultado.TileY = (*CEntity::EntityList)[i]->TileY;
		}

		Resultado.ColidiuA = Resultado.ColidiuA || ResultadoTemp.ColidiuA;
		Resultado.ColidiuB = Resultado.ColidiuB || ResultadoTemp.ColidiuB;
		Resultado.ColidiuC = Resultado.ColidiuC || ResultadoTemp.ColidiuC;
		Resultado.ColidiuD = Resultado.ColidiuD || ResultadoTemp.ColidiuD;

	}
	return Resultado;
}

bool CEntity::IsTrash() {
	return Trash;
}

void CEntity::ProcessaColisao(CEntity* Entidade, TipoColisao TpColisao) {
	//
}

CRetangulo CEntity::GetRetangulo() {
	CRetangulo Retangulo;
	Retangulo.A = (int) (Y + (Height * PorcentagemFisicaHeight));
	Retangulo.B = X + Width;
	Retangulo.C = Y + Height;
	Retangulo.D = X;
	return Retangulo;
}



